package ${packageName};

<#list beanImports as imports>
import ${imports};
</#list>

/**
 * ${tableName}
 */
public class ${d_tableName} {

	public static final String TABLE_NAME = "${tableName}";
	public static final String CLASS_NAME = "${d_tableName}"; 
	static final int MAX_GET = Short.MAX_VALUE;
	
	//索引名称
	<#list indexKeys as index>
	public static final String  <#list index.d_columnNames as d_columnName>${d_columnName}</#list>_IndexName = "<#list index.x_columnNames as x_columnName>${x_columnName}</#list>";
	</#list>
	
	//对象版本号	
	private int _v = 0;
	public int _nextVer(){
		if(_v > MAX_GET) _v = 0;
		return ++_v;
	}
	
	public int _getVer(){
		return _v;
	}
	
	//是否是源对象
	private boolean _source = false;
	
	public boolean is_source() {
		return _source;
	}

	public void set_source(boolean _source) {
		this._source = _source;
	}
	
	//Cache 中的索引
	<#list indexKeys as index>
	<#if index.unique>
	private String  <#list index.x_columnNames as x_columnName>${x_columnName}</#list>_Unique = null;
	<#else>
	private String  <#list index.x_columnNames as x_columnName>${x_columnName}</#list>_Index = null;
	</#if>
	</#list>
	public ${d_tableName} updatePrimaryIndex(){
		return updatePrimaryIndex(this);
	}
	
	public static List<${d_tableName}> updatePrimaryIndex(List<${d_tableName}> ${x_tableName}s){
		for(${d_tableName} ${x_tableName} : ${x_tableName}s){
			updatePrimaryIndex(${x_tableName});	
		}
		return ${x_tableName}s;
	}
	
	public static ${d_tableName} updatePrimaryIndex(${d_tableName} ${x_tableName}){
		<#assign i=0 />
		<#list indexKeys as index>
		<#if i==0>
		String field = ${index.all_d_columnName_get};
		<#assign i=1 />
		<#else>
		field = ${index.all_d_columnName_get};
		</#if>
		<#if index.unique>
		${x_tableName}.set<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_Unique(field);
		<#else>
		${x_tableName}.set<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_Index(field);
		</#if>
		
		</#list>
		return ${x_tableName};
	}
	
	
	/**
	 * 需要更新字段集
	 */
	private Map<String, Object> updateColumns;

	/* 可能需要补救的字段 */
	private SK_ByteBuff byteBuff = SK_ByteBuff.allocate();
	
	public SK_ByteBuff getSK_ByteBuff(){
		return this.byteBuff;
	}
	
	<#list columns as column>
	/** ${column.remarks} */
	private ${column.basicType} ${column.x_columnName};
	
	</#list>
	
	public ${d_tableName}() {
		super();
		this._source = true;
	}
	
	public ${d_tableName}(${all_basicType_x_columnName}) {
		super();
		<#list columns as column>
		this.${column.x_columnName} = ${column.x_columnName};
		</#list>
		this._source = true;
	}
	
	<#-- 取得更新字段集 -->
	public Map<String, Object> getUpdateColumns() {
		if(updateColumns == null)
			updateColumns = new HashMap<String, Object>();
		return updateColumns;
	}
	
	public void setUpdateColumns(Map<String, Object> updateColumns) {
		this.updateColumns = updateColumns;
	}
	
	<#assign i=0 />
	<#-- Get And Set -->
	<#list columns as column>
	public ${column.basicType} get${column.d_columnName}() {
		return ${column.x_columnName};
	}
	
	<#assign i=i+1 />
	public void set${column.d_columnName}(${column.basicType} ${column.x_columnName}) {
		changeSet${column.d_columnName}(${column.x_columnName});
		if(!this._source){
			byteBuff.writeInt(${i});
			<#if column.basicType=="short">
			byteBuff.writeShort(${column.x_columnName});
			<#elseif column.basicType=="int">
			byteBuff.writeInt(${column.x_columnName});
			<#elseif column.basicType=="long">
			byteBuff.writeLong(${column.x_columnName});
			<#elseif column.basicType=="float">
			byteBuff.writeFloat(${column.x_columnName});
			<#elseif column.basicType=="double">
			byteBuff.writeDouble(${column.x_columnName});
			<#elseif column.basicType=="Date" || column.basicType=="java.util.Date">
			byteBuff.writeDate(${column.x_columnName});
			<#elseif column.basicType=="String">
			byteBuff.writeString(${column.x_columnName});
			</#if>	
		}
	}
	
	private void changeSet${column.d_columnName}(${column.basicType} ${column.x_columnName}) {
		this.${column.x_columnName} = ${column.x_columnName};
		if(!this._source){
			addUpdateColumn("${column.columnName}",${column.x_columnName});
		}
	}
	
	<#-- 数值类型字段Change操作 -->
	<#if column.basicType=="short" || column.basicType=="int" || column.basicType=="long" || column.basicType=="float" || column.basicType=="double">
	<#assign i=i+1 />
	public void change${column.d_columnName}With(${column.basicType} ${column.x_columnName}){
		this.${column.x_columnName} += ${column.x_columnName};
		changeSet${column.d_columnName}(this.${column.x_columnName});
		//不是源对象才记录变更操作
		if(!this._source){
			byteBuff.writeInt(${i});
			<#if column.basicType=="short">
			byteBuff.writeShort(${column.x_columnName});
			<#elseif column.basicType=="int">
			byteBuff.writeInt(${column.x_columnName});
			<#elseif column.basicType=="long">
			byteBuff.writeLong(${column.x_columnName});
			<#elseif column.basicType=="float">
			byteBuff.writeFloat(${column.x_columnName});
			<#elseif column.basicType=="double">
			byteBuff.writeDouble(${column.x_columnName});
			</#if>	
		}
	}
	<#assign i=i+1 />
	public void change${column.d_columnName}WithMin(${column.basicType} ${column.x_columnName},${column.basicType} min){
		this.${column.x_columnName} += ${column.x_columnName};
		this.${column.x_columnName} = this.${column.x_columnName} < min ? min : this.${column.x_columnName};
		changeSet${column.d_columnName}(this.${column.x_columnName});
		//不是源对象才记录变更操作
		if(!this._source){
			byteBuff.writeInt(${i});
			<#if column.basicType=="short">
			byteBuff.writeShort(${column.x_columnName});
			byteBuff.writeShort(min);
			<#elseif column.basicType=="int">
			byteBuff.writeInt(${column.x_columnName});
			byteBuff.writeInt(min);
			<#elseif column.basicType=="long">
			byteBuff.writeLong(${column.x_columnName});
			byteBuff.writeLong(min);
			<#elseif column.basicType=="float">
			byteBuff.writeFloat(${column.x_columnName});
			byteBuff.writeFloat(min);
			<#elseif column.basicType=="double">
			byteBuff.writeDouble(${column.x_columnName});
			byteBuff.writeDouble(min);
			</#if>
		}	
	}
	<#assign i=i+1 />
	public void change${column.d_columnName}WithMax(${column.basicType} ${column.x_columnName},${column.basicType} max){
		this.${column.x_columnName} += ${column.x_columnName};
		this.${column.x_columnName} = this.${column.x_columnName} > max ? max : this.${column.x_columnName};
		changeSet${column.d_columnName}(this.${column.x_columnName});
		//不是源对象才记录变更操作
		if(!this._source){
			byteBuff.writeInt(${i});
			<#if column.basicType=="short">
			byteBuff.writeShort(${column.x_columnName});
			byteBuff.writeShort(max);
			<#elseif column.basicType=="int">
			byteBuff.writeInt(${column.x_columnName});
			byteBuff.writeInt(max);
			<#elseif column.basicType=="long">
			byteBuff.writeLong(${column.x_columnName});
			byteBuff.writeLong(max);
			<#elseif column.basicType=="float">
			byteBuff.writeFloat(${column.x_columnName});
			byteBuff.writeFloat(max);
			<#elseif column.basicType=="double">
			byteBuff.writeDouble(${column.x_columnName});
			byteBuff.writeDouble(max);
			</#if>
		}
	}
	<#assign i=i+1 />
	public void change${column.d_columnName}WithMaxMin(${column.basicType} ${column.x_columnName},${column.basicType} max,${column.basicType} min){
		this.${column.x_columnName} += ${column.x_columnName};
		this.${column.x_columnName} = this.${column.x_columnName} < min ? min : this.${column.x_columnName};
		this.${column.x_columnName} = this.${column.x_columnName} > max ? max : this.${column.x_columnName};
		changeSet${column.d_columnName}(this.${column.x_columnName});
		//不是源对象才记录变更操作
		if(!this._source){
			byteBuff.writeInt(${i});
			<#if column.basicType=="short">
			byteBuff.writeShort(${column.x_columnName});
			byteBuff.writeShort(max);
			byteBuff.writeShort(min);
			<#elseif column.basicType=="int">
			byteBuff.writeInt(${column.x_columnName});
			byteBuff.writeInt(max);
			byteBuff.writeInt(min);
			<#elseif column.basicType=="long">
			byteBuff.writeLong(${column.x_columnName});
			byteBuff.writeLong(max);
			byteBuff.writeLong(min);
			<#elseif column.basicType=="float">
			byteBuff.writeFloat(${column.x_columnName});
			byteBuff.writeFloat(max);
			byteBuff.writeFloat(min);
			<#elseif column.basicType=="double">
			byteBuff.writeDouble(${column.x_columnName});
			byteBuff.writeDouble(max);
			byteBuff.writeDouble(min);
			</#if>
		}	
	}	
	</#if>
	</#list>
	
	<#-- 主外键关联查询 -->
	<#list bindKeys as bindKey>
	<#if bindKey.pk>
	//${bindKey.fkColumnName}
	<#-- 主键 -->
	public ${bindKey.d_pkTableName} get${bindKey.d_pkTableName}Pk${bindKey.d_fkColumnName}(){
		return ${bindKey.d_pkTableName}Imp.getBy${bindKey.d_pkColumnName}(${bindKey.x_fkColumnName});
	}
	<#else>
	//${bindKey.pkColumnName}
	<#if bindKey.unique>
	<#-- 1对1 -->
	public ${bindKey.d_fkTableName} get${bindKey.d_fkTableName}sFk${bindKey.d_fkColumnName}(){
		return ${bindKey.d_fkTableName}Imp.getBy${bindKey.d_fkColumnName}(${bindKey.x_pkColumnName});
	}
	
	<#else>
	<#-- 1对多 -->
	public List<${bindKey.d_fkTableName}> get${bindKey.d_fkTableName}sFk${bindKey.d_fkColumnName}(){
		return ${bindKey.d_fkTableName}Imp.getBy${bindKey.d_fkColumnName}(${bindKey.x_pkColumnName});
	}
	
	</#if>
	</#if>
	</#list>
	<#-- 添加更新字段集 -->
	public void addUpdateColumn(String key, Object val) {
		Map<String, Object> map = getUpdateColumns();
		if (map == null)
			return;
		map.put(key, val);
	}
	/**
	<#-- 取得更新字段集 -->
	public void clearUpdateColumn() {
		Map<String, Object> map = getUpdateColumns();
		if (map == null)
			return;
		map.clear();
	}
	*/
	public ${d_tableName} clone(){
		${d_tableName} ${x_tableName} = new ${d_tableName}();
		<#list columns as column>
		${x_tableName}.set${column.d_columnName}(this.get${column.d_columnName}());
		</#list>
		${x_tableName}._v = _v;
		${x_tableName}._source = false;
		return ${x_tableName}.updatePrimaryIndex(); 
	}
	
	<#-- 对象转换 -->
	public Map<String, Object> toMap(){
        Map<String, Object> result = new HashMap<String, Object>();
        <#list columns as column>
        result.put("${column.x_columnName}", this.${column.x_columnName});
        </#list>
        return result;
    }
    
    public String toString(){
        return toMap().toString();
    }
    
    public String toJson(){
    	return JSON.toJSONString(toMap());
    }
    
    /**
     * 数据库源字段Map
     */
    public Map<String, Object> toColumnNameMap(){
        Map<String, Object> result = new HashMap<String, Object>();
        <#list columns as column>
        result.put("${column.columnName}", this.${column.x_columnName});
        </#list>
        return result;
    }
    
    public String toColumnNameString(){
        return toColumnNameMap().toString();
    }
    
    public byte[] toBytes() throws Exception {
    	SK_ByteBuff byteBuff = SK_ByteBuff.allocate();
    	<#list columns as column>
	    <#if column.basicType=="int">
	    byteBuff.writeInt(this.${column.x_columnName});
	    <#elseif column.basicType=="long">
	    byteBuff.writeLong(this.${column.x_columnName});
	    <#elseif column.basicType=="short">
	    byteBuff.writeShort(this.${column.x_columnName});
	    <#elseif column.basicType=="float">
	    byteBuff.writeFloat(this.${column.x_columnName});
	    <#elseif column.basicType=="double">
	    byteBuff.writeDouble(this.${column.x_columnName});
	    <#elseif column.basicType=="Date" || column.basicType=="java.util.Date">
	    byteBuff.writeDate(this.${column.x_columnName});
	    <#elseif column.basicType=="String">
	    byteBuff.writeString(this.${column.x_columnName});
	    </#if>
	    </#list>
	    return byteBuff.toByte();
    }
    
    public byte[] toSKBytes(){
    	SK_ByteBuff byteBuff = SK_ByteBuff.allocate();
    	byteBuff.writeMap(toMap());
	    return byteBuff.toByte();
    }
    
     public static ${d_tableName} createForBytes(byte[] _byte) throws Exception {
     	SK_ByteBuff byteBuff = SK_ByteBuff.wrap(_byte);
     	${d_tableName} ${x_tableName} = new ${d_tableName}();
    	<#list columns as column>
	    <#if column.basicType=="int">
	    ${x_tableName}.${column.x_columnName} = byteBuff.readInt(null);
	    <#elseif column.basicType=="long">
	    ${x_tableName}.${column.x_columnName} = byteBuff.readLong(null);
	    <#elseif column.basicType=="short">
	    ${x_tableName}.${column.x_columnName} = byteBuff.readShort(null);
	    <#elseif column.basicType=="float">
	    ${x_tableName}.${column.x_columnName} = byteBuff.readFloat(null);
	    <#elseif column.basicType=="double">
	    ${x_tableName}.${column.x_columnName} = byteBuff.readDouble(null);
	    <#elseif column.basicType=="Date" || column.basicType=="java.util.Date">
	    ${x_tableName}.${column.x_columnName} = byteBuff.readDate(null);
	    <#elseif column.basicType=="String">
	    ${x_tableName}.${column.x_columnName} = byteBuff.readString(null);
	    </#if>
	    </#list>
	    return ${x_tableName}.updatePrimaryIndex();
     }
     
     public static ${d_tableName} createForSKBytes(byte[] _byte){
     		SK_ByteBuff byteBuff = SK_ByteBuff.wrap(_byte);
     		@SuppressWarnings("unchecked")
     		Map<String,Object> map = byteBuff.readMap(null);
	     	${d_tableName} ${x_tableName} = ${d_tableName}.createForMap(map);
		    return ${x_tableName}.updatePrimaryIndex();
     }
    
    /**
     * 根据list创建对象
     */
    public static List<${d_tableName}> createForColumnNameList(List<Map<String, Object>> list){
    	List<${d_tableName}> ${x_tableName}s = new ArrayList<${d_tableName}>();
		for (Map<String, Object> map : list) {
			${x_tableName}s.add(createForColumnNameMap(map));
		}
		return ${x_tableName}s;
    }
    
    /**
     * 根据map创建对象
     */
    public static ${d_tableName} createForColumnNameMap(Map<String, Object> map){
    	${d_tableName} obj = new ${d_tableName}();
		<#list columns as column>
	    <#if column.basicType=="int">
	    obj.${column.x_columnName} = SK_Map.getInt("${column.columnName}", map);
	    <#elseif column.basicType=="long">
	    obj.${column.x_columnName} = SK_Map.getLong("${column.columnName}", map);
	    <#elseif column.basicType=="short">
	    obj.${column.x_columnName} = SK_Map.getShort("${column.columnName}", map);
	    <#elseif column.basicType=="float">
	    obj.${column.x_columnName} = SK_Map.getFloat("${column.columnName}", map);
	    <#elseif column.basicType=="double">
	    obj.${column.x_columnName} = SK_Map.getDouble("${column.columnName}", map);
	    <#elseif column.basicType=="Date" || column.basicType=="java.util.Date">
	    obj.${column.x_columnName} = SK_Map.getDate("${column.columnName}", map);
	    <#elseif column.basicType=="String">
	    obj.${column.x_columnName} = SK_Map.getString("${column.columnName}", map);
	    </#if>
	    </#list>
        return obj.updatePrimaryIndex();
    }
    
    /**
     * 根据list创建对象
     */
    public static List<${d_tableName}> createForList(List<Map<String, Object>> list){
    	List<${d_tableName}> ${x_tableName}s = new ArrayList<${d_tableName}>();
		for (Map<String, Object> map : list) {
			${x_tableName}s.add(createForColumnNameMap(map));
		}
		return ${x_tableName}s;
    }
    
    /**
     * 根据map创建对象
     */
    public static ${d_tableName} createForMap(Map<String, Object> map){
    	${d_tableName} obj = new ${d_tableName}();
		<#list columns as column>
	    <#if column.basicType=="int">
	    obj.${column.x_columnName} = SK_Map.getInt("${column.x_columnName}", map);
	    <#elseif column.basicType=="long">
	    obj.${column.x_columnName} = SK_Map.getLong("${column.x_columnName}", map);
	    <#elseif column.basicType=="short">
	    obj.${column.x_columnName} = SK_Map.getShort("${column.x_columnName}", map);
	    <#elseif column.basicType=="float">
	    obj.${column.x_columnName} = SK_Map.getFloat("${column.x_columnName}", map);
	    <#elseif column.basicType=="double">
	    obj.${column.x_columnName} = SK_Map.getDouble("${column.x_columnName}", map);
	    <#elseif column.basicType=="Date" || column.basicType=="java.util.Date">
	    obj.${column.x_columnName} = SK_Map.getDate("${column.x_columnName}", map);
	    <#elseif column.basicType=="String">
	    obj.${column.x_columnName} = SK_Map.getString("${column.x_columnName}", map);
	    </#if>
	    </#list>
        return obj.updatePrimaryIndex();
    }
    
    public static ${d_tableName} createForJson(String json){
    	Map<String, Object> map = JSON.parseObject(json);
    	return createForMap(map);
    }
    
    public static List<${d_tableName}> createForJson(List<String> jsons){
    	List<${d_tableName}> ${x_tableName}s = new ArrayList<${d_tableName}>();
    	for(String json : jsons){
    		${x_tableName}s.add(createForJson(json));
    	}
    	return ${x_tableName}s;
    }
    
    /** 级联删除(延迟入库) */
    public boolean deleteAndSon(){
    	return false;
    }
    
    /** 级联删除(及时入库) */
    public boolean deleteAndSonAndFlush(){
    	return false;
    }
    
    /** 延迟插入数据库 */
    public ${d_tableName} insert(){
    	return ${d_tableName}Imp.insert(this);
    }
    /** 延迟更新数据库 */
    public ${d_tableName} update(){
    	return ${d_tableName}Imp.update(this);
    }
    /** 延迟删除数据库 */
    public boolean delete(){
    	return ${d_tableName}Imp.delete(this);
    }
    /** 即时插入数据库 */
    public ${d_tableName} insertAndFlush(){
    	return ${d_tableName}Imp.insertAndFlush(this);
    }
    /** 即时更新数据库 */
    public ${d_tableName} updateAndFlush(){
    	return ${d_tableName}Imp.updateAndFlush(this);
    }
    /** 即时删除数据库 */
    public boolean deleteAndFlush(){
    	return ${d_tableName}Imp.deleteAndFlush(this);
    }
    
    
    
    //--------------------------------Cache 中的索引 GET & SET
	<#list indexKeys as index>
	<#if index.unique>
	public String get<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_Unique(){
		return <#list index.x_columnNames as x_columnName>${x_columnName}</#list>_Unique;
	}
	
	public void set<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_Unique(String <#list index.x_columnNames as x_columnName>${x_columnName}</#list>_Unique){
		this.<#list index.x_columnNames as x_columnName>${x_columnName}</#list>_Unique = <#list index.x_columnNames as x_columnName>${x_columnName}</#list>_Unique;
	}
	<#else>
	public String get<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_Index(){
		return <#list index.x_columnNames as x_columnName>${x_columnName}</#list>_Index;
	}
	
	public void set<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_Index(String <#list index.x_columnNames as x_columnName>${x_columnName}</#list>_Index){
		this.<#list index.x_columnNames as x_columnName>${x_columnName}</#list>_Index = <#list index.x_columnNames as x_columnName>${x_columnName}</#list>_Index;
	}
	</#if>
	
	</#list>
	
	
	/** 取得改变的索引 */
	public Map<String,String> getUpdateIndexs(){
		Map<String,String> indexNames = new HashMap<String,String>();
		<#list indexKeys as index>
		<#if index.unique>
		if(!this.get<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_Unique().equals(SK_Plus.b(${index.all_x_columnName_}).e())){
			indexNames.put(${d_tableName}.<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_IndexName,SK_Plus.b(${index.all_x_columnName_}).e());
			indexNames.put("isUpdtaeUnique","true");
		}
		<#else>
		if(!this.get<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_Index().equals(SK_Plus.b(${index.all_x_columnName_}).e()))
			indexNames.put(${d_tableName}.<#list index.d_columnNames as d_columnName>${d_columnName}</#list>_IndexName,SK_Plus.b(${index.all_x_columnName_}).e());
		</#if>			
			
		</#list>
		return indexNames;
	}
}